package com.fuelwallet.view;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.SearchRecentSuggestions;
import android.text.Html;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.fuelwallet.R;
import com.fuelwallet.model.CarProfile;
import com.fuelwallet.model.CarProfileHandle;
import com.fuelwallet.model.CurrentAccount;
import com.fuelwallet.model.LineItemizedOverlay;
import com.fuelwallet.model.MySuggestionProvider;
import com.fuelwallet.model.PlacesItemizedOverlay;
import com.fuelwallet.model.SearchedPlacesHistoryHandle;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class BaseMapActivity extends MapActivity {
	// Debugging
	private static final String TAG = "BaseMapActivity";
	private static final boolean D = true;
	// Intent request codes
	public static final int REQUEST_OBTAIN_DIRECTION = 2;
	// Start options
	public static final String LAUNCH_OPTIONS = "options";
	public static final int OPTION_GET_DIRECTION = 10;
	public static final int OPTION_SEARCH_PLACE = 11;
	// Dialog IDs
	public static final int DIALOG_LAYERS = 20;
	public static final int DIALOG_DIRECTION_PROGRESS = 21;
	public static final int DIALOG_ACCOUNTS = 22;
	public static final int DIALOG_EXIT = 23;
	public static final int DIALOG_UNPROPER_ADDRESS = 24;
	public static final int DIALOG_SEARCH_PROGRESS = 25;
	public static final int DIALOG_NETWORK_DOWN = 26;
	public static final int DIALOG_CHOOSE_DIRECTION = 27;
	// Message what
	public static final int MESSAGE_LAUNCH_DIRECTION = 30;
	public static final int MESSAGE_DIRECTION_CHOICE = 31;
	
	private MapView mapView;
	private TextView routeInfoView;
	private EditText searchText;
	private ImageView image_layer;
	private ImageView image_account;
	private ImageView image_my_location;

	private CarProfileHandle carProfiles;
	private List<String> carNameList;
	private String[] carNameItems;
	private String currentCarName;
	private CurrentAccount curCar;
	private int current_index;
	
	private List<Overlay> mapOverlays;
	private MapController mc;
	private MyLocationOverlay mylayer;
	private LocationManager locationManager;
	private Location currentLocation;
	private Drawable placeDefault, startDefault, endDefault;
	private PlacesItemizedOverlay searchedItemizedOverlay, startItemizedOverlay, endItemizedOverlay;
	private Geocoder gc;
	private SearchedPlacesHistoryHandle searchHistoryHandle;
	
	private Handler mHandler = new Handler(){
		private int current_index = 0;
		public void handleMessage(Message msg){
			switch(msg.what){
			case MESSAGE_LAUNCH_DIRECTION:
				current_index = msg.arg1;
				BaseMapActivity.this.showDialog(DIALOG_CHOOSE_DIRECTION);
				break;
			case MESSAGE_DIRECTION_CHOICE:
				String currentAddress = searchedItemizedOverlay.getItem(current_index).getTitle();
				Intent intent1 = new Intent(BaseMapActivity.this, ObtainDirectionActivity.class);
				// Set this flag to ensure that a new instance of the activity will
				// be created when launch it
				intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
				
				int choice = msg.arg1;
				if(choice == 0)	//Start from here				
					intent1.putExtra(ObtainDirectionActivity.FROM, currentAddress);					
				else if(choice == 1)	//End to here
					intent1.putExtra(ObtainDirectionActivity.TO, currentAddress);
					
				BaseMapActivity.this.startActivityForResult(intent1, REQUEST_OBTAIN_DIRECTION);
				overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
				break;
			}		
		}
	};
	/*
	private int route_duration = 0; // in seconds
	private int route_distance = 0; // in meters
	private String route_distance_toshow;
	private String route_duration_toshow;
	private String route_start_address;
	private String route_end_address;
	*/

	private LocationListener myLocationListener = new LocationListener() {

		public void onLocationChanged(Location location) {
			currentLocation = location;
		}

		public void onProviderDisabled(String provider) {

		}

		public void onProviderEnabled(String provider) {

		}

		public void onStatusChanged(String provider, int status, Bundle extras) {

		}
	};

	@Override
	protected boolean isRouteDisplayed() {
		return true;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.base_map);

		searchText = (EditText) findViewById(R.id.search_edittext);
		searchText.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				onSearchRequested();
			}
		});
		image_layer = (ImageView) findViewById(R.id.image_layer);
		image_layer.setOnClickListener(new View.OnClickListener() {			
			public void onClick(View v) {
				BaseMapActivity.this.showDialog(DIALOG_LAYERS);
			}
		});
		image_account = (ImageView) findViewById(R.id.image_account);
		image_account.setOnClickListener(new View.OnClickListener() {			
			public void onClick(View v) {
				BaseMapActivity.this.showDialog(DIALOG_ACCOUNTS);
			}
		});		
		image_my_location = (ImageView) findViewById(R.id.image_my_location);
		image_my_location.setOnClickListener(new View.OnClickListener() {			
			public void onClick(View v) {
				mc.animateTo(mylayer.getMyLocation());
			}
		});
		routeInfoView = (TextView) findViewById(R.id.route_info_textview);
		
		carProfiles = new CarProfileHandle(this);
		curCar = new CurrentAccount(this);		
		gc = new Geocoder(this);
		searchHistoryHandle = new SearchedPlacesHistoryHandle(this);
		mapSetup();
	}

	@Override
	protected void onStart() {
		super.onStart();

		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				1000, 0, myLocationListener);
		locationManager.requestLocationUpdates(
				LocationManager.NETWORK_PROVIDER, 1000, 0, myLocationListener);
		mylayer.enableMyLocation();
		mylayer.enableCompass();

		if (locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) != null) {
			currentLocation = locationManager
					.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		} else if (locationManager
				.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) != null) {
			currentLocation = locationManager
					.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
		}	
	}

	@Override
	protected void onStop() {
		super.onPause();

		locationManager.removeUpdates(myLocationListener);
		mylayer.disableCompass();
		mylayer.disableMyLocation();
	}

	private void mapSetup() {
		mapView = (MapView) findViewById(R.id.mapview);
		mapView.setBuiltInZoomControls(true);

		mc = mapView.getController();
		mc.setZoom(18);

		locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

		mapOverlays = mapView.getOverlays();
		mylayer = new MyLocationOverlay(this, mapView);
		mylayer.enableCompass();
		mylayer.enableMyLocation();
		mylayer.runOnFirstFix(new Runnable() {
			public void run() {
				mc.animateTo(mylayer.getMyLocation());
			}
		});
		mapOverlays.add(mylayer);

		placeDefault = getResources().getDrawable(R.drawable.marker_dot_green);
		startDefault = getResources().getDrawable(R.drawable.da_marker_red);
		endDefault = getResources().getDrawable(R.drawable.da_marker_blue);
		searchedItemizedOverlay = new PlacesItemizedOverlay(placeDefault, mapView, mHandler);
		endItemizedOverlay = new PlacesItemizedOverlay(endDefault, mapView, mHandler);
		startItemizedOverlay = new PlacesItemizedOverlay(startDefault, mapView, mHandler);
		mapOverlays.add(searchedItemizedOverlay);
		mapOverlays.add(startItemizedOverlay);
		mapOverlays.add(endItemizedOverlay);		
	}
	
	public boolean isNetworkOnline() {
	    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	    NetworkInfo netInfo = cm.getActiveNetworkInfo();
	    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
	        return true;
	    }
	    return false;
	}
	
	protected Dialog onCreateDialog(int id){
		switch(id){
		case DIALOG_LAYERS:
			AlertDialog.Builder layerBuilder = new AlertDialog.Builder(this);
			boolean[] initial = {false, false, true};
			
			layerBuilder.setTitle(R.string.dialog_title_layer);
			layerBuilder.setMultiChoiceItems(R.array.map_layers, initial, new DialogInterface.OnMultiChoiceClickListener() {				
				public void onClick(DialogInterface dialog, int which, boolean isChecked) {
					return;
				}
			});
			layerBuilder.setPositiveButton(R.string.dialog_positive_btn, new DialogInterface.OnClickListener() {				
				public void onClick(DialogInterface dialog, int which) {
					SparseBooleanArray checkStates = ((AlertDialog)dialog).getListView().getCheckedItemPositions();
					int pos;
					mapView.setSatellite(checkStates.get(0));
					mapView.setTraffic(checkStates.get(1));
					if(checkStates.get(2)){
						pos = mapOverlays.indexOf(mylayer);
						if(pos == -1)							
							mapOverlays.add(mylayer);							
					}else{
						pos = mapOverlays.indexOf(mylayer);
						if(pos != -1)
							mapOverlays.remove(pos);
					}
					mapView.invalidate();
				}
			});
			layerBuilder.setNegativeButton(R.string.dialog_negative_btn, new DialogInterface.OnClickListener() {				
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
			return layerBuilder.create();
		case DIALOG_DIRECTION_PROGRESS:
			ProgressDialog progressDialog = new ProgressDialog(this);
			progressDialog.setTitle(R.string.dialog_title_obtain_direction);
			progressDialog.setMessage(getResources().getString(R.string.dialog_message_obtain_direction));
			progressDialog.setIndeterminate(true);
    		progressDialog.setCancelable(true);
    		return progressDialog;
		case DIALOG_SEARCH_PROGRESS:
			ProgressDialog searchProgressDialog = new ProgressDialog(this);
			//searchProgressDialog.setTitle("");
			searchProgressDialog.setMessage("Searching. Please wait...");
			searchProgressDialog.setIndeterminate(true);
			searchProgressDialog.setCancelable(true);
    		return searchProgressDialog;
		case DIALOG_ACCOUNTS:
			AlertDialog.Builder accountBuilder = new AlertDialog.Builder(this);
			
			carProfiles.open();
				carNameList = carProfiles.getAccountNameList();
				carNameItems = new String[carNameList.size()];
				carNameList.toArray(carNameItems);
			carProfiles.close();
			curCar.open();
				currentCarName = curCar.getCurrentAccount().getAccountName();
			curCar.close();
			
			current_index = carNameList.indexOf(currentCarName);
			if(current_index == -1)
				current_index = 0;
			
			accountBuilder.setTitle(R.string.dialog_title_account);			
			accountBuilder.setSingleChoiceItems(carNameItems, current_index, null);
			accountBuilder.setPositiveButton(R.string.dialog_positive_btn, new DialogInterface.OnClickListener(){
				public void onClick(DialogInterface dialog, int which) {
					int checkedPosition = ((AlertDialog)dialog).getListView().getCheckedItemPosition();						
					curCar.open();
					carProfiles.open();
						CarProfile current = carProfiles.getCarProfile(carNameList.get(checkedPosition));
						curCar.setCurrentAccount(current);
						if(D) Log.i(TAG, "After Dialog: " + curCar.getCurrentAccount().getAccountName());
					carProfiles.close();
					curCar.close();
					
					//Toast.makeText(BaseMapActivity.this, "Current car set successful!", Toast.LENGTH_SHORT).show();					
				}				
			});
			accountBuilder.setNegativeButton(R.string.dialog_negative_btn, new DialogInterface.OnClickListener() {				
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
			return accountBuilder.create();
		case DIALOG_CHOOSE_DIRECTION:
			AlertDialog.Builder directionBuilder = new AlertDialog.Builder(this);
			
			directionBuilder.setTitle("Find your route from here");
			directionBuilder.setSingleChoiceItems(R.array.direction_choices, -1, new DialogInterface.OnClickListener() {				
				public void onClick(DialogInterface dialog, int which) {
					mHandler.obtainMessage(BaseMapActivity.MESSAGE_DIRECTION_CHOICE, which, -1)
							.sendToTarget();
					dialog.dismiss();
				}
			});
			directionBuilder.setNegativeButton(R.string.dialog_negative_btn, new DialogInterface.OnClickListener() {						
				   public void onClick(DialogInterface dialog, int which) {
					    dialog.cancel();
				   }
			   });
			return directionBuilder.create();
		case DIALOG_EXIT:
			AlertDialog.Builder exitBuilder = new AlertDialog.Builder(this);
			
			exitBuilder.setMessage(R.string.dialog_message_exit)
					   .setCancelable(false)
					   .setPositiveButton(R.string.dialog_positive_btn_exit, new DialogInterface.OnClickListener() {						
						   public void onClick(DialogInterface dialog, int which) {
							    dialog.dismiss();
								BaseMapActivity.this.finish();		
								overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
						   }
					   })
					   .setNegativeButton(R.string.dialog_negative_btn_exit, new DialogInterface.OnClickListener() {						
						   public void onClick(DialogInterface dialog, int which) {
							    dialog.cancel();
						   }
					   });
			AlertDialog exitDialog = exitBuilder.create();
			return exitDialog;		
		case DIALOG_UNPROPER_ADDRESS:
			AlertDialog.Builder adb = new AlertDialog.Builder(this);
            adb.setTitle("Search Map");
            adb.setMessage("Cannot find it.Please Provide a Proper Place!");
            adb.setPositiveButton("Close", new DialogInterface.OnClickListener() {				
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
            return adb.create();
		case DIALOG_NETWORK_DOWN:
			AlertDialog.Builder downBuilder = new AlertDialog.Builder(this);
			downBuilder.setTitle("Network Down");
			downBuilder.setMessage("Your network connection is down. Please reconnect it for further usage.");
			downBuilder.setPositiveButton("Close", new DialogInterface.OnClickListener() {				
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
			return downBuilder.create();
		default:
			return null;
		}
	}

	protected void onPrepareDialog(int id, Dialog dialog){
		switch(id){
		case DIALOG_LAYERS:
			ListView internal = ((AlertDialog)dialog).getListView();
			internal.setItemChecked(0, mapView.isSatellite());
			internal.setItemChecked(1, mapView.isTraffic());
			internal.setItemChecked(2, (mapOverlays.indexOf(mylayer) == -1) ? false : true);
			break;
		case DIALOG_CHOOSE_DIRECTION:
			ListView internal1 = ((AlertDialog)dialog).getListView();
			internal1.setItemChecked(0, false);
			internal1.setItemChecked(1, false);
			break;
		case DIALOG_ACCOUNTS:			
			carProfiles.open();
				carNameList = carProfiles.getAccountNameList();
				carNameItems = new String[carNameList.size()];
				carNameList.toArray(carNameItems);
			carProfiles.close();
			curCar.open();
				currentCarName = curCar.getCurrentAccount().getAccountName();
				if(D) Log.i(TAG, "Prepare Dialog: currentCarName = " + currentCarName);
			curCar.close();
			
			current_index = carNameList.indexOf(currentCarName);
			if(D) Log.i(TAG, "Prepare Dialog: current_index = " + current_index);
			if(current_index == -1)
				current_index = 0;
			
			ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_singlechoice, carNameList);
			((AlertDialog)dialog).getListView().setAdapter(adapter);
			((AlertDialog)dialog).getListView().setItemChecked(current_index, true);
			
			break;
		default:
			super.onPrepareDialog(id, dialog);				
		}
	}
	
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.base_map_menu, menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		Intent intent1;
		switch (item.getItemId()) {
		case R.id.menu_clear_route:			
			startItemizedOverlay.clearOverlayItems();
			endItemizedOverlay.clearOverlayItems();
			
			mapOverlays.clear();
			mapOverlays.add(mylayer);
			mapOverlays.add(searchedItemizedOverlay);
			mapOverlays.add(startItemizedOverlay);
			mapOverlays.add(endItemizedOverlay);
			
			routeInfoView.setVisibility(View.GONE);
			mapView.invalidate();
			return true;
		case R.id.menu_direction:
			intent1 = new Intent(BaseMapActivity.this, ObtainDirectionActivity.class);
			// Set this flag to ensure that a new instance of the activity will
			// be created when launch it
			intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			BaseMapActivity.this.startActivityForResult(intent1, REQUEST_OBTAIN_DIRECTION);
			overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
			return true;
		case R.id.menu_clear_map:
			searchedItemizedOverlay.clearOverlayItems();
			startItemizedOverlay.clearOverlayItems();
			endItemizedOverlay.clearOverlayItems();

			mapOverlays.clear();
			mapOverlays.add(mylayer);
			mapOverlays.add(searchedItemizedOverlay);
			mapOverlays.add(startItemizedOverlay);
			mapOverlays.add(endItemizedOverlay);
			
			routeInfoView.setVisibility(View.GONE);
			mapView.invalidate();
			return true;
		case R.id.menu_setting:
			intent1 = new Intent(BaseMapActivity.this, SettingActivity.class);
			BaseMapActivity.this.startActivity(intent1);
			//overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
			overridePendingTransition(android.R.anim.slide_in_left,android.R.anim.slide_out_right);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	// called when start this activity from other activities on top of it
	public void onNewIntent(Intent intent){
		int option = intent.getIntExtra(LAUNCH_OPTIONS, -1);
		
		switch(option){
		case OPTION_GET_DIRECTION:
			// clear current routes on map
			startItemizedOverlay.clearOverlayItems();
			endItemizedOverlay.clearOverlayItems();
			
			mapOverlays.clear();
			mapOverlays.add(mylayer);
			mapOverlays.add(searchedItemizedOverlay);
			mapOverlays.add(startItemizedOverlay);
			mapOverlays.add(endItemizedOverlay);
			
			routeInfoView.setVisibility(View.GONE);
			mapView.invalidate();
			
			// start new activity for route search
			Intent intent1 = new Intent(BaseMapActivity.this, ObtainDirectionActivity.class);
			// Set this flag to ensure that a new instance of the activity will
			// be created when launch it
			intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			BaseMapActivity.this.startActivityForResult(intent1, REQUEST_OBTAIN_DIRECTION);
			break;
		case -1:
			// check if it is the search 
			if(Intent.ACTION_SEARCH.equals(intent.getAction())){
				this.showDialog(DIALOG_SEARCH_PROGRESS);
		    	// handles a search query
		        String query = intent.getStringExtra(SearchManager.QUERY);
		        
		        // update history
		        searchHistoryHandle.open();
    				searchHistoryHandle.putPlace(query);
    			searchHistoryHandle.close();
		            
		        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
		                    MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
		        suggestions.saveRecentQuery(query, null);
		            
		        showSearchResult(query);
		    }
			break;
		default:
			break;
		}	
	}
	
	private void showSearchResult(String query){
		List<Address> addresses;			
		
		if(query.toLowerCase().equals("my location")){
			this.dismissDialog(DIALOG_SEARCH_PROGRESS);
			mc.animateTo(mylayer.getMyLocation());
			searchText.setText(query);
			return;
		}
		
		try {
			addresses = gc.getFromLocationName(query, 5);
		} catch (IOException e) {
			// if(isNetworkOnline() == false){
			this.showDialog(DIALOG_NETWORK_DOWN);
			// }
			return;
		}

		searchText.setText(query);
		if (addresses.size() > 0) {
			this.dismissDialog(DIALOG_SEARCH_PROGRESS);

			GeoPoint point = new GeoPoint(
					(int) (addresses.get(0).getLatitude() * 1E6),
					(int) (addresses.get(0).getLongitude() * 1E6));
			OverlayItem overlayitem = new OverlayItem(point, query, "");
			searchedItemizedOverlay.addOverlay(overlayitem);
			mc.animateTo(point);
			// mapView.invalidate();
		} else {
			this.showDialog(DIALOG_UNPROPER_ADDRESS);
		}		
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (D)
			Log.d(TAG, "onActivityResult " + resultCode);

		switch (requestCode) {
		case BaseMapActivity.REQUEST_OBTAIN_DIRECTION:
			if (resultCode == Activity.RESULT_OK) {
				String _from = data.getStringExtra(ObtainDirectionActivity.FROM);
				String _to = data.getStringExtra(ObtainDirectionActivity.TO);

				if (_from.equals(_to))
					return;
				
				this.showDialog(DIALOG_DIRECTION_PROGRESS);				
				try {
					if (_from.toLowerCase().equals("my location")) {
						new GoogleDirection().execute(
								currentLocation.getLatitude() + "," + currentLocation.getLongitude(),
								URLEncoder.encode(_to, "UTF-8"),
								//URLEncoder.encode(_from, "UTF-8"), URLEncoder.encode(_to, "UTF-8"));
								_from, _to);
					} else if (_to.toLowerCase().equals("my location")) {						
						new GoogleDirection().execute(
								URLEncoder.encode(_from, "UTF-8"), 
								currentLocation.getLatitude() + ","	+ currentLocation.getLongitude(),
								//URLEncoder.encode(_from, "UTF-8"), URLEncoder.encode(_to, "UTF-8"));
								_from, _to);
					} else {
						new GoogleDirection().execute(
								URLEncoder.encode(_from, "UTF-8"),
								URLEncoder.encode(_to, "UTF-8"),
								//URLEncoder.encode(_from, "UTF-8"), URLEncoder.encode(_to, "UTF-8"));
								_from, _to);
					}
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			} // else if(resultCode == Activity.RESULT_CANCELED)
			break;
		default:
			break;
		}
	}
	
	public void onBackPressed(){
		showDialog(DIALOG_EXIT);		
	}

	private class GoogleDirection extends AsyncTask<String, Integer, List<GeoPoint>> {
		private final String mapAPI = "http://maps.googleapis.com/maps/api/directions/json?"
				+ "origin={0}&destination={1}&sensor=true";
		private String _from_format, _from_original;
		private String _to_format, _to_original;
		private List<GeoPoint> _points = new ArrayList<GeoPoint>();
		private JSONObject _route;
		
		private int route_duration = 0; // in seconds
		private int route_distance = 0; // in meters
		private double start_lat;
		private double start_lng;
		private double end_lat;
		private double end_lng;
		private String route_distance_toshow;
		private String route_duration_toshow;
		private String route_start_address;
		private String route_end_address;

		@Override
		protected List<GeoPoint> doInBackground(String... params) {
			if (params.length < 0)
				return null;

			_from_format = params[0];
			_to_format = params[1];			
			String url = MessageFormat.format(mapAPI, _from_format, _to_format);			
			Log.i(TAG, url);

			_from_original = params[2];
			_to_original = params[3];
			
			HttpGet get = new HttpGet(url);
			String strResult = "";
			try {
				HttpParams httpParameters = new BasicHttpParams();
				HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
				HttpClient httpClient = new DefaultHttpClient(httpParameters);

				HttpResponse httpResponse = null;
				httpResponse = httpClient.execute(get);

				if (httpResponse.getStatusLine().getStatusCode() == 200) {
					strResult = EntityUtils.toString(httpResponse.getEntity());

					JSONObject jsonObject = new JSONObject(strResult);
					String statusCode = jsonObject.getString("status");

					if (statusCode.equals("OK")) {
						JSONArray routeObject = jsonObject
								.getJSONArray("routes");
						_route = routeObject.getJSONObject(0);
						String polyline = _route.getJSONObject(
								"overview_polyline").getString("points");

						if (polyline.length() > 0)
							decodePolylines(polyline);

						return _points;
					} else
						return null;
				} else
					return null;
			} catch (Exception e) {
				Log.e(TAG, e.toString());
				return null;
			}

		}

		@Override
		protected void onPostExecute(List<GeoPoint> points){
			if (points != null && points.size() > 0 && _route != null){
				LineItemizedOverlay mOverlay = new LineItemizedOverlay(points);				
				mapOverlays.add(mOverlay);				
				
				try {
					JSONArray legsArray = _route.getJSONArray("legs");
					JSONObject durationObject, distanceObject, startLocObject, endLocObject;
					//int numOfLegs = legsArray.length();
					//for(int i = 0; i < numOfLegs; i++){
					durationObject = legsArray.getJSONObject(0).getJSONObject("duration");
					distanceObject = legsArray.getJSONObject(0).getJSONObject("distance");
					startLocObject = legsArray.getJSONObject(0).getJSONObject("start_location");
					endLocObject = legsArray.getJSONObject(0).getJSONObject("end_location");
					route_duration = durationObject.getInt("value");
					route_duration_toshow = durationObject.getString("text");
					route_distance = distanceObject.getInt("value");
					route_distance_toshow = distanceObject.getString("text");
					route_start_address = legsArray.getJSONObject(0).getString("start_address");
					route_end_address = legsArray.getJSONObject(0).getString("end_address");
					//}			
					start_lat = startLocObject.getDouble("lat");
					start_lng = startLocObject.getDouble("lng");
					end_lat = endLocObject.getDouble("lat");
					end_lng = endLocObject.getDouble("lng");
					GeoPoint start_point = new GeoPoint((int)(start_lat * 1E6), (int)(start_lng * 1E6));
					GeoPoint end_point = new GeoPoint((int)(end_lat * 1E6), (int)(end_lng * 1E6));
					OverlayItem start_overlay = new OverlayItem(start_point, _from_original, "");
					OverlayItem end_overlay = new OverlayItem(end_point, _to_original, "");
					startItemizedOverlay.addOverlay(start_overlay);
					endItemizedOverlay.addOverlay(end_overlay);
					
					StringBuffer routeInfo = new StringBuffer();
					routeInfo.append("To <b>").append(route_end_address).append("</b>: <br>")
							.append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;").append(route_duration_toshow)
							.append(" - ").append(route_distance_toshow).append(" (tap for details)");					
					
					routeInfoView.setText(Html.fromHtml(routeInfo.toString()));
					routeInfoView.setOnClickListener(new View.OnClickListener() {						
						public void onClick(View v) {
							Intent intent = new Intent(BaseMapActivity.this, ShowReportActivity.class);
							intent.putExtra(ShowReportActivity.START_ADDRESS, route_start_address);
							intent.putExtra(ShowReportActivity.END_ADDRESS, route_end_address);
							intent.putExtra(ShowReportActivity.ROUTE_DISTANCE, route_distance);
							intent.putExtra(ShowReportActivity.ROUTE_DURATION, route_duration);
							intent.putExtra(ShowReportActivity.ROUTE_DISTANCE_TOSHOW, route_distance_toshow);
							intent.putExtra(ShowReportActivity.ROUTE_DURATION_TOSHOW, route_duration_toshow);
							BaseMapActivity.this.startActivity(intent);
							overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
						}
					});
					routeInfoView.setVisibility(View.VISIBLE);
					
					mapView.invalidate();
					BaseMapActivity.this.dismissDialog(DIALOG_DIRECTION_PROGRESS);					
				} catch (JSONException e) {
					Log.e(TAG, e.toString());
					return;
				}
			} else {
				Toast.makeText(BaseMapActivity.this, "No route information is found!", Toast.LENGTH_LONG).show();
				BaseMapActivity.this.dismissDialog(DIALOG_DIRECTION_PROGRESS);	
			}
		}

		private void decodePolylines(String poly) {
			int len = poly.length();
			int index = 0;
			int lat = 0;
			int lng = 0;

			while (index < len) {
				int b, shift = 0, result = 0;
				do {
					b = poly.charAt(index++) - 63;
					result |= (b & 0x1f) << shift;
					shift += 5;
				} while (b >= 0x20);
				int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
				lat += dlat;

				shift = 0;
				result = 0;
				do {
					b = poly.charAt(index++) - 63;
					result |= (b & 0x1f) << shift;
					shift += 5;
				} while (b >= 0x20);
				int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
				lng += dlng;

				GeoPoint p = new GeoPoint((int) ((lat / 1E5) * 1E6),
						(int) ((lng / 1E5) * 1E6));
				_points.add(p);
			}
		}
	}

}